home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume91 / news / barn_201 / part01 / article.c next >
C/C++ Source or Header  |  1991-02-07  |  9KB  |  316 lines

  1. /*
  2.  *    File Name:        article.c
  3.  *    Project:        BARN - Bah's Amiga ReadNews.
  4.  *    Purpose:        Parse header fields in a news article.
  5.  *    Functions:        ParseArticle, GetNextHeader, DumpArticle, DestroyArticle.
  6.  *    Author:            Jeff Van Epps
  7.  *    Created:        02 Sep 89
  8.  *    Last Modified:    05 Jan 91
  9.  *    Comments:
  10.  *    History:
  11.  *        02 Sep 89/JVE    Created.
  12.  *        28 Sep 89/JVE    ParseArticle now stores position within file where
  13.  *                        headers end and text begins in article->textpos.
  14.  *        30 Dec 89/JVE    Added "Sender:" to list of useful headers.  This list
  15.  *                        will go away when there is a config file to do same.
  16.  *        18 Oct 90/JVE    Use HDR_xxx defines instead of hardcoded strings.
  17.  *                        Added GetHeader.
  18.  *        21 Oct 90/JVE    Don't end header search until blank line.
  19.  *        05 Jan 91/JVE    New "subject" field in article_info initialized to
  20.  *                        a NULL pointer and set to point at the SUBJECT header
  21.  *                        fieldvalue after all headers have been read.
  22.  */
  23.  
  24. # include    <stdio.h>
  25. # include    <stdlib.h>
  26. # include    <string.h>
  27. # include    "standard.h"
  28. # include    "article.h"
  29. # include    "configure.h"
  30. # include    "variables.h"
  31.  
  32.  
  33. /****************************************************************************/
  34. /*    FUNCTION:    ParseArticle                                                */
  35. /*                                                                            */
  36. /*    PURPOSE:    Parses headers from article & creates article/header structs*/
  37. /*                                                                            */
  38. /*    INPUT PARAMETERS:                                                        */
  39. /*        NAME        I/O        DESCRIPTION                                        */
  40. /*        ----        ---        -----------                                        */
  41. /*        filename     I        Name of file containing article.                */
  42. /*                                                                            */
  43. /*    RETURNS:                                                                */
  44. /*        (ARTICLE_INFO *)    Pointer to newly allocated article structure.    */
  45. /*        NULLP(ARTICLE_INFO)    Indication of failure.                            */
  46. /*                                                                            */
  47. /*    COMMENTS:                                                                */
  48. /*        Assumes filename contains only digits and is same as article         */
  49. /*        number.                                                                */
  50. /*                                                                            */
  51. /*    HISTORY:                                                                */
  52. /*        1.    02 Sep 89        Created.                                        */
  53. /*        2.    28 Sep 89        Added textpos to say where headers end.            */
  54. /*                                                                            */
  55. /****************************************************************************/
  56.  
  57. ARTICLE_INFO *ParseArticle( filename )
  58.  
  59. char    *filename;
  60.  
  61. {
  62. FILE            *fp;
  63. long            id;            /* article number (aka filename) */
  64. ARTICLE_INFO    *article;    /* ptr to article information */
  65. HEADER_INFO        **hdr;        /* handle for header field allocation */
  66. HEADER_INFO        *h;
  67.  
  68. if ( ( fp = fopen( filename, "r" ) ) == NULLP( FILE ) )
  69.     {
  70.     perror( filename );
  71.     return NULLP( ARTICLE_INFO );
  72.     }
  73. else if ( ( id = atol( filename ) ) <= 0 )
  74.     {
  75.     printf( "%s: Bad article number.\n", filename );
  76.     return NULLP( ARTICLE_INFO );
  77.     }
  78.  
  79. /*
  80.  *    Initialize article info structure.
  81.  */
  82.  
  83. article = (ARTICLE_INFO *) malloc( sizeof( ARTICLE_INFO ) );
  84. article->number = id;
  85. article->next = NULLP( ARTICLE_INFO );
  86. article->headers = NULLP( HEADER_INFO );
  87. article->beenread = FALSE;
  88. article->textpos = 0L;
  89. article->done = FALSE;
  90. article->subject = NULLP( char );
  91.  
  92. /*
  93.  *    Get all header fields.
  94.  */
  95.  
  96. hdr = &article->headers;
  97. while ( GetNextHeader( fp, &hdr ) ) 
  98.     article->textpos = ftell( fp );
  99. fclose( fp );
  100. for ( h = article -> headers; h != NULLP( HEADER_INFO ); h = h -> next )
  101.     if ( strcmp( h -> fieldname, HDR_SUBJECT ) == 0 )
  102.         {
  103.         article -> subject = h -> fieldvalue;
  104.         break;
  105.         }
  106. return article;
  107. }
  108.  
  109.  
  110. /****************************************************************************/
  111. /*    FUNCTION:    GetNextHeader                                                */
  112. /*                                                                            */
  113. /*    PURPOSE:    Parses the next header field out of an article.                */
  114. /*                                                                            */
  115. /*    INPUT PARAMETERS:                                                        */
  116. /*        NAME        I/O        DESCRIPTION                                        */
  117. /*        ----        ---        -----------                                        */
  118. /*        fp             I        FILE pointer to file containing article.        */
  119. /*        hdr            I/O        Where to put pointer to newly allocated            */
  120. /*                            HEADER_INFO structure if we allocate one.        */
  121. /*                                                                            */
  122. /*    RETURNS:                                                                */
  123. /*        TRUE    Successfully parsed another header from article.            */
  124. /*        FALSE    Failed/no more headers in article.                            */
  125. /*                                                                            */
  126. /*    COMMENTS:                                                                */
  127. /*        Adjusts hdr when done so next call will set correct pointer.        */
  128. /*        BBS version terminates header search on a line without a colon,        */
  129. /*        or with a space before the colon.  Usenet version terminates        */
  130. /*        header search on blank line, ignoring "malformed" header lines.        */
  131. /*                                                                            */
  132. /*    HISTORY:                                                                */
  133. /*        1.    02 Sep 89        Created.                                        */
  134. /*        2.    30 Dec 89        Added "Sender:" to list of useful headers.        */
  135. /*        3.    21 Oct 90        Don't end header search until blank line.        */
  136. /*                                                                            */
  137. /****************************************************************************/
  138.  
  139. GetNextHeader( fp, hdr )
  140.  
  141. FILE            *fp;
  142. HEADER_INFO        ***hdr;
  143.  
  144. {
  145. int                rc;                /* return code from function */
  146. char            buf[BUFSIZ];    /* holds input line from article */
  147. char            *firstspace, *firstcolon, *data;    /* for parsing */
  148.  
  149. if ( fgets( buf, BUFSIZ, fp ) == NULL )
  150.     rc = FALSE;
  151. else
  152.     {
  153.     firstspace = strchr( buf, ' ' );
  154.     firstcolon = strchr( buf, ':' );
  155.     if ( ( firstcolon == NULL ) || 
  156.         ( ( firstspace != NULL ) && ( firstspace < firstcolon ) ) )
  157.             {
  158.             if ( GetVar( VAR_BBS ) || strspn( buf, " \t\r\n" ) == strlen(buf) )
  159.                 rc = FALSE;
  160.             else                    /* junk line, don't end header search */
  161.                 rc = TRUE;
  162.             }
  163.     else
  164.         {
  165.         *firstcolon = NULL;        /* terminate fieldname string */
  166. # ifndef ARN_CONFIG
  167. /*
  168.  *    Until a useful way is found to restrict output to interesting headers,
  169.  *    use this kluge.
  170.  *
  171.  *    Don't actually allocate a header struct because we're not interested in
  172.  *    other headers, but return TRUE so that we continue to try to get headers.
  173.  */
  174.     if ( strcmp( buf, HDR_FROM ) && strcmp( buf, HDR_SUBJECT ) &&
  175.         strcmp( buf, HDR_DATE ) && strcmp( buf, HDR_SENDER ) && 
  176.         strcmp( buf, HDR_TO ) )
  177.             return TRUE;
  178. # endif
  179.         firstcolon++;            /* advance past colon/NULL to value string */
  180.         data = firstcolon + strspn( firstcolon, " \t" );    /* skip white */
  181.         data[strlen(data)-1] = NULL;    /* remove trailing newline */
  182.  
  183.         /*
  184.          *    Allocate and fill a new header structure.
  185.          */
  186.  
  187.         **hdr = (HEADER_INFO *) malloc( sizeof( HEADER_INFO ) );
  188.         (**hdr)->fieldname = strdup( buf );
  189.         (**hdr)->fieldvalue = strdup( data );
  190.         (**hdr)->next = NULLP( HEADER_INFO );
  191.  
  192.         /*
  193.          *    Reset the hdr pointer so next call will continue chain correctly.
  194.          */
  195.  
  196.         *hdr = &((**hdr)->next);
  197.         rc = TRUE;
  198.         }
  199.     }
  200. return rc;
  201. }
  202.  
  203.  
  204. /****************************************************************************/
  205. /*    FUNCTION:    DumpArticle                                                    */
  206. /*                                                                            */
  207. /*    PURPOSE:    Print article/header info for an article.                    */
  208. /*                                                                            */
  209. /*    INPUT PARAMETERS:                                                        */
  210. /*        NAME        I/O        DESCRIPTION                                        */
  211. /*        ----        ---        -----------                                        */
  212. /*        article         I        Pointer to article structure to dump.            */
  213. /*                                                                            */
  214. /*    RETURNS: none                                                            */
  215. /*                                                                            */
  216. /*    COMMENTS:                                                                */
  217. /*        Debugging function.                                                    */
  218. /*                                                                            */
  219. /*    HISTORY:                                                                */
  220. /*        1.    02 Sep 89        Created.                                        */
  221. /*                                                                            */
  222. /****************************************************************************/
  223.  
  224. void DumpArticle( article )
  225.  
  226. ARTICLE_INFO    *article;
  227.  
  228. {
  229. HEADER_INFO        *hdr;
  230.  
  231. printf( "Article: %ld\n", article->number );
  232. for ( hdr = article->headers; hdr != NULLP( HEADER_INFO ); hdr = hdr->next )
  233.     printf( "\t%s: %s\n", hdr->fieldname, hdr->fieldvalue );
  234. printf( "\n" );
  235. }
  236.  
  237.  
  238. /****************************************************************************/
  239. /*    FUNCTION:    DestroyArticle                                                */
  240. /*                                                                            */
  241. /*    PURPOSE:    Free all space taken by article/header structure.            */
  242. /*                                                                            */
  243. /*    INPUT PARAMETERS:                                                        */
  244. /*        NAME        I/O        DESCRIPTION                                        */
  245. /*        ----        ---        -----------                                        */
  246. /*        article         I        The article being destroyed.                    */
  247. /*                                                                            */
  248. /*    RETURNS:                                                                */
  249. /*                                                                            */
  250. /*    COMMENTS:                                                                */
  251. /*                                                                            */
  252. /*    HISTORY:                                                                */
  253. /*        1.    02 Sep 89        Created.                                        */
  254. /*                                                                            */
  255. /****************************************************************************/
  256.  
  257. void DestroyArticle( article )
  258.  
  259. ARTICLE_INFO    *article;
  260.  
  261. {
  262. HEADER_INFO        *hdr, *tmp;
  263.  
  264. for ( hdr = article->headers; hdr != NULLP( HEADER_INFO ); hdr = tmp )
  265.     {
  266.     free( hdr->fieldname );
  267.     free( hdr->fieldvalue );
  268.     tmp = hdr->next;
  269.     free( hdr );
  270.     }
  271. free( article );
  272. }
  273.  
  274.  
  275. /****************************************************************************/
  276. /*    FUNCTION:    GetHeader                                                    */
  277. /*                                                                            */
  278. /*    PURPOSE:    Retrieve a specific header from a message.                    */
  279. /*                                                                            */
  280. /*    INPUT PARAMETERS:                                                        */
  281. /*        NAME        I/O        DESCRIPTION                                        */
  282. /*        ----        ---        -----------                                        */
  283. /*        headers         I        List of headers.                                */
  284. /*        name         I        Name of header to retrieve.                        */
  285. /*                                                                            */
  286. /*    RETURNS:                                                                */
  287. /*                                                                            */
  288. /*    COMMENTS:                                                                */
  289. /*        Makes a local copy of the header value to be returned.  Gets        */
  290. /*        overwritten each call.                                                */
  291. /*                                                                            */
  292. /*    HISTORY:                                                                */
  293. /*        1.    18 Oct 90        Created.                                        */
  294. /*                                                                            */
  295. /****************************************************************************/
  296.  
  297. char    *GetHeader( headers, name )
  298.  
  299. HEADER_INFO        *headers;
  300. char            *name;
  301.  
  302. {
  303. static char        local[MAXLINE];
  304.  
  305. while ( headers )
  306.     {
  307.     if ( strcmp( headers -> fieldname, name ) == 0 )
  308.         {
  309.         strcpy( local, headers -> fieldvalue );
  310.         return local;
  311.         }
  312.     headers = headers -> next;
  313.     }
  314. return (char *) NULL;
  315. }
  316.